home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / hc / tex05_sr.sit / appendDeleteFiles 0.5.c next >
Text File  |  1988-09-04  |  7KB  |  295 lines

  1. /* new HyperCard XFCN to append or delete files
  2.  * copyright 1988 Mark ^Zimmermann - 880901-0904
  3.  * part of the TEX HyperCard package as an additional tool for
  4.  * dataspace creation and navigation...
  5.  *
  6.  * Call this XFCN as "appendDeleteFiles (cmd)".  If cmd begins with the
  7.  * letter 'A', then a standard files dialog will offer a list of TEXT
  8.  * files; if one is selected, then the offer will be repeated and
  9.  * subsequent selections will be appended to the end of the first
  10.  * one.  If cmd begins with the letter 'D', then files selected from
  11.  * the std files dialog (which shows all files now, now just TEXT files)
  12.  * will be irreversably (probably? barring low-level magic) deleted.
  13.  *
  14.  * Error checking is minimal, and the usual response to an error is
  15.  * to quit with some short message and a beep....
  16.  */
  17.  
  18.  
  19. #include <MacTypes.h>
  20. #include <FileMgr.h>
  21. #include <StdFilePkg.h>
  22. #include <HyperXCmd.h>
  23.  
  24. #define NULL  0
  25.  
  26. /* define these to allow use of global variables in my XFCNs; a
  27.  * Lightspeed C necessity, apparently...
  28.  */
  29.  
  30. #define SetUpA4()        asm  {    move.l a4,-(sp)        \
  31.                                 move.l a0,a4    }
  32.  
  33. #define RestoreA4()        asm  {    move.l (sp)+,a4    }
  34.  
  35.  
  36. pascal void main (XCmdBlockPtr paramPtr);
  37. void doAppend (XCmdBlockPtr paramPtr);
  38. void doDelete (XCmdBlockPtr paramPtr);
  39. int appendNextFile (int baseFileRefNum, Str255 *nextFileName,
  40.   int nextVolRefNum, char *bufp, long myBufSize, XCmdBlockPtr paramPtr);
  41. int adzGetFile (Str255 *fileNamePtr, int *volRefNumPtr, int numTypes);
  42. void returnErrorMsg (XCmdBlockPtr paramPtr, char *msg);
  43. char *strcpy (char *s1, char *s2);
  44. int strlen (char *s);
  45.  
  46.  
  47. pascal void main (paramPtr)
  48.   XCmdBlockPtr paramPtr;
  49.   {
  50.     SetUpA4();
  51.     switch (**(paramPtr->params[0]))
  52.       {
  53.           case 'A':
  54.               doAppend (paramPtr);
  55.               break;
  56.           case 'D':
  57.               doDelete (paramPtr);
  58.               break;
  59.           default:
  60.               returnErrorMsg (paramPtr,
  61.                 "{Sorry, unrecognized command in appendDeleteFiles call!}");
  62.               break;
  63.       }
  64.     RestoreA4();
  65.     return;
  66.   }
  67.  
  68.  
  69. /* function to do the work of appending files to the end of the
  70.  * first-chosen one... determine buffer size automatically
  71.  */
  72.  
  73. void doAppend (paramPtr)
  74.   XCmdBlockPtr paramPtr;
  75.   {
  76.     Str255 basefileName, nextFileName;
  77.     int baseVolRefNum, baseFileRefNum, nextVolRefNum, nextFileRefNum;
  78.     long myBufSize, grow;
  79.     char *bufp;
  80.     
  81.     if (adzGetFile (&basefileName, &baseVolRefNum,1))
  82.       {
  83.         if (FSOpen (basefileName, baseVolRefNum, &baseFileRefNum) != noErr)
  84.           {
  85.               returnErrorMsg (paramPtr,
  86.                 "{Sorry, error while trying to open the base file!}");
  87.               return;
  88.             }
  89.  
  90.         /* see how much memory we can get for our buffer here */
  91.         MaxApplZone();
  92.         myBufSize = MaxMem (&grow) - 32768;  /* keep 32kB in reserve */
  93.         if ((bufp = NewPtr (myBufSize)) == NULL)
  94.           {
  95.               returnErrorMsg (paramPtr,
  96.                 "{Sorry, memory manager error while getting buffer space!}");
  97.               return;
  98.             }
  99.  
  100.         while (adzGetFile (&nextFileName, &nextVolRefNum, 1) &&
  101.             appendNextFile (baseFileRefNum, &nextFileName, nextVolRefNum,
  102.                                 bufp, myBufSize, paramPtr))
  103.             ;
  104.  
  105.         DisposPtr (bufp);
  106.         FSClose (baseFileRefNum);
  107.       }
  108.  
  109.     return;
  110.   }
  111.  
  112.  
  113. /* function to do the work of deleting files as they are chosen ... no
  114.  * particular error checking, just try to do it until 'Cancel' ... beep
  115.  * and return a polite message if unable to comply for some reason....
  116.  */
  117.  
  118. void doDelete (paramPtr)
  119.   XCmdBlockPtr paramPtr;
  120.   {
  121.     Str255 fileName;
  122.     int volRefNum;
  123.  
  124.     while (adzGetFile (&fileName, &volRefNum, -1))
  125.         if (FSDelete (fileName, volRefNum) != noErr)
  126.           {
  127.               returnErrorMsg (paramPtr,
  128.                 "{Sorry, file system error while trying to delete a file!}");
  129.               break;
  130.             }
  131.     
  132.     return;
  133.   }
  134.  
  135.  
  136. /* routine to append the contents of nextFile X to baseFile ... does some
  137.  * limited error checking and tries to get a polite msg back to user if
  138.  * there is a problem ... returns 1 if all is well, 0 on error....
  139.  */
  140.  
  141. int appendNextFile (baseFileRefNum, nextFileName, nextVolRefNum,
  142.                         bufp, myBufSize, paramPtr)
  143.   int baseFileRefNum, nextVolRefNum;
  144.   Str255 *nextFileName;
  145.   char *bufp;
  146.   long myBufSize;
  147.   XCmdBlockPtr paramPtr;
  148.   {
  149.     int nextFileRefNum, errNum;
  150.     long count;
  151.     
  152.     errNum = FSOpen (nextFileName, nextVolRefNum, &nextFileRefNum);
  153.     if (errNum != noErr && errNum != opWrErr)    /* ok if read-only here */
  154.       {
  155.         returnErrorMsg (paramPtr,
  156.            "{Sorry, error while attempting to open file to be appended!}");
  157.          return (0);
  158.        }
  159.  
  160.     if (SetFPos (nextFileRefNum, fsFromStart, 0L) != noErr)
  161.       {
  162.         returnErrorMsg (paramPtr,
  163.            "{Sorry, error setting pointer in file to be appended!}");
  164.           FSClose (nextFileRefNum);
  165.           return (0);
  166.       }
  167.     if (SetFPos (baseFileRefNum, fsFromLEOF, 0L) != noErr)
  168.       {
  169.         returnErrorMsg (paramPtr,
  170.            "{Sorry, error setting pointer to end of base file!}");
  171.           FSClose (nextFileRefNum);
  172.           return (0);
  173.       }
  174.     for (;;)
  175.       {
  176.         count = myBufSize;
  177.         errNum = FSRead (nextFileRefNum, &count, bufp);
  178.         if (errNum != noErr && errNum != eofErr)
  179.           {
  180.             returnErrorMsg (paramPtr,
  181.                "{Sorry, error while reading from file to be appended!}");
  182.               FSClose (nextFileRefNum);
  183.               return (0);
  184.           }
  185.         if (count == 0)
  186.             break;
  187.         if (FSWrite (baseFileRefNum, &count, bufp) != noErr)
  188.           {
  189.             returnErrorMsg (paramPtr,
  190.                "{Sorry, error while writing to base file!}");
  191.               FSClose (nextFileRefNum);
  192.               return (0);
  193.           }
  194.       }
  195.     FSClose (nextFileRefNum);
  196.     return (1);                    /* success, at last! */
  197.   }
  198.  
  199.  
  200. /* this routine gets the name of the file to be appended or deleted ...
  201.  * pass it numTypes = 1 for restricting the Std Files Dialog view
  202.  * to type 'TEXT' only, or pass numTypes = -1 to show all files.
  203.  * The function returns 1 if a file was selected (and copies the file
  204.  * name into the place pointed to by fileNamePtr and the volume number
  205.  * into the place pointed to by volRefNumPtr), and returns 0 if the
  206.  * user chooses 'Cancel'....
  207.  */
  208.  
  209. int adzGetFile (fileNamePtr, volRefNumPtr, numTypes)
  210.   Str255 *fileNamePtr;
  211.   int *volRefNumPtr;
  212.   int numTypes;
  213.   {
  214.     SFTypeList myFileTypes;
  215.     Point SFGwhere;
  216.     SFReply myReply;
  217.     register int i;
  218.  
  219.     SFGwhere.v = 90;
  220.     SFGwhere.h = 82;
  221.     myFileTypes[0] = 'TEXT';
  222.     
  223.     SFGetFile (SFGwhere, "\p", 0L, numTypes, myFileTypes, 0L, &myReply);
  224.     
  225.     if (myReply.good)
  226.       {
  227.         for (i = *myReply.fName; i >= 0; --i)
  228.             (*fileNamePtr)[i] = myReply.fName[i];
  229.         *volRefNumPtr = myReply.vRefNum;
  230.         return (1);
  231.       }
  232.     else
  233.         return (0);
  234.   }
  235.  
  236.  
  237. /* function to set the return value of the XFCN to a chosen error msg;
  238.  * if there isn't enough free memory to give us a Handle to the msg,
  239.  * beep a bunch and then return!
  240.  */
  241.  
  242. void returnErrorMsg (paramPtr, msg)
  243.   XCmdBlockPtr paramPtr;
  244.   char *msg;
  245.   {
  246.     Handle answer;
  247.     int msgLength;
  248.     
  249.     SysBeep (10);
  250.     msgLength = strlen (msg);
  251.     if ((answer = NewHandle (1 + msgLength)) == NULL)
  252.       {
  253.         SysBeep (10);
  254.         SysBeep (10);
  255.         SysBeep (10);
  256.         SysBeep (10);
  257.         SysBeep (10);
  258.         return;
  259.       }
  260.  
  261.     strcpy (*answer, msg);
  262.     paramPtr->returnValue = answer;
  263.     return;
  264.   }
  265.  
  266.  
  267. /* function to determine the length of a string ... standard thing,
  268.  * adapted from the LSC library, and K&R p.98 ....
  269.  */
  270.  
  271. int strlen (s)
  272.   register char *s;
  273.   {
  274.     char *s0 = s;
  275.  
  276.     while (*s++)
  277.         ;
  278.     return (s - s0 - 1);
  279.   }
  280.  
  281.  
  282. /* function to copy a string from one place to another, in a rather
  283.  * obvious fashion ... adapted from the LSC library, and K&R p.101 ....
  284.  */
  285.  
  286. char *strcpy (s1, s2)
  287.   register char *s1, *s2;
  288.   {
  289.     char *s = s1;
  290.     
  291.     while (*s1++ = *s2++)
  292.         ;
  293.     return (s);
  294.   }
  295.